package com.jelly.common.note;

import com.jelly.common.constant.Constant;
import com.jelly.common.util.AddressUtil;
import com.jelly.common.util.StringUtils;
import com.jelly.common.util.web.JsonUtil;
import com.jelly.common.util.web.RequestContextHolderUtil;
import com.jelly.config.shiro.token.TokenUtil;
import com.jelly.web.modules.monitor.log.domain.OperLog;
import com.jelly.web.modules.monitor.log.service.IOperLogService;
import com.jelly.web.modules.staff.user.domain.User;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @创建人 ql
 * @创建时间 2018-08-17 15:34
 * @功能描述: 注解类切面
 **/
@Aspect
@Component
@EnableAsync
public class OperateAspect {

    @Autowired
    private IOperLogService operLogService;

    // 配置织入点
    @Pointcut("@annotation(com.jelly.common.note.OperationLog)")
    public void logPointCut(){}
    /**
     * 前置通知 用于拦截操作
     *
     * @param joinPoint 切点
     */
    @AfterReturning(pointcut = "logPointCut()")
    public void doBefore(JoinPoint joinPoint){
        handleLog(joinPoint, null);
    }

    /**
     * 拦截异常操作
     *
     * @param joinPoint
     * @param e
     */
    @AfterThrowing(value = "logPointCut()", throwing = "e")
    public void doAfter(JoinPoint joinPoint, Exception e){
        handleLog(joinPoint, e);
    }
    @Async
    protected void handleLog(final JoinPoint joinPoint, final Exception e){

        try{

            // 获得注解
            OperationLog controllerLog = getAnnotationLog(joinPoint);

            if (controllerLog == null){
                return;
            }

            // 获取当前的用户
            User user = TokenUtil.getToken();
            //新增操作日志
            OperLog operLog = new OperLog();
            operLog.setAddId(user.getUserId());
            operLog.setDeptId(user.getDeptId());
            operLog.setLogParam(JsonUtil.objectToJson(RequestContextHolderUtil.getRequest().getParameterMap()));
            String ip = RequestContextHolderUtil.getIPAddress();
            operLog.setLogIp(ip);
            operLog.setLogUrl(RequestContextHolderUtil.getHttpServletRequestUrl());
            operLog.setLogChannel(RequestContextHolderUtil.mobileDevice());
            operLog.setLogLocation(AddressUtil.getRealAddressByIP(ip));
            operLog.setIsState(Constant.SUCCESS);

            if(null != e){
                operLog.setIsState(Constant.ERROR);
                operLog.setErrorMsg(StringUtils.substring(e.getMessage(),0,2000));
            }
            // 设置方法名称
            String className = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            operLog.setLogClass(className);
            operLog.setLogMethod(methodName+ "()");

            operLog.setLogName(controllerLog.name());
            operLog.setLogAction(controllerLog.value());
            operLogService.insterOperLog(operLog);

        }catch (Exception exception){
            System.out.println(exception.getMessage());
        }

    }

    /**
     * 是否存在注解，如果存在就获取
     */
    private OperationLog getAnnotationLog(JoinPoint joinPoint) throws Exception
    {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();

        if (method != null)
        {
            return method.getAnnotation(OperationLog.class);
        }
        return null;
    }

}
